package org.tp8.sampleapp.view;

import java.io.IOException;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;

import org.apache.commons.lang.StringUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.security.web.savedrequest.SavedRequest;
import org.tp8.sampleapp.util.SampleAppLogger;

/**
 * The Class LoginBean.
 */
@ManagedBean(name = "loginBean")
@SessionScoped
public class LoginBean extends AbstractBean {

	/** The Constant log. */
	private final static SampleAppLogger log = new SampleAppLogger(
			LoginBean.class);

	/** The authentication manager. */
	@ManagedProperty(value = "#{authenticationManager}")
	private AuthenticationManager authenticationManager;

	/** The username. */
	private String username;

	/** The password. */
	private String password;

	/**
	 * Gets the authentication manager.
	 * 
	 * @return the authenticationManager
	 */
	public AuthenticationManager getAuthenticationManager() {
		return authenticationManager;
	}

	/**
	 * Sets the authentication manager.
	 * 
	 * @param authenticationManager
	 *            the authenticationManager to set
	 */
	public void setAuthenticationManager(
			AuthenticationManager authenticationManager) {
		this.authenticationManager = authenticationManager;
	}

	/**
	 * Gets the username.
	 * 
	 * @return the username
	 */
	public String getUsername() {
		return username;
	}

	/**
	 * Sets the username.
	 * 
	 * @param username
	 *            the username to set
	 */
	public void setUsername(String username) {
		this.username = username;
	}

	/**
	 * Gets the password.
	 * 
	 * @return the password
	 */
	public String getPassword() {
		return password;
	}

	/**
	 * Sets the password.
	 * 
	 * @param password
	 *            the password to set
	 */
	public void setPassword(String password) {
		this.password = password;
	}

	/**
	 * Do login.
	 * 
	 * @return the string
	 */
	public String doLogin() {
		try {
			log.info("Login started for User with Name: " + getUsername());

			// check if userdata is given
			if (StringUtils.isBlank(getUsername())
					|| StringUtils.isBlank(getPassword())) {
				FacesMessage facesMsg = new FacesMessage(
						FacesMessage.SEVERITY_ERROR, "Error", "login.failed");
				FacesContext.getCurrentInstance().addMessage(null, facesMsg);
				log.info("Login not started because userName or Password is empty: "
						+ getUsername());
				return null;
			}

			// authenticate afainst spring security
			Authentication request = new UsernamePasswordAuthenticationToken(
					getUsername(), getPassword());

			// AuthenticationManager authenticationManager =
			// (AuthenticationManager) appContext
			// .getBean("authenticationManager");
			Authentication result = authenticationManager.authenticate(request);
			SecurityContextHolder.getContext().setAuthentication(result);

		} catch (AuthenticationException e) {
			log.warn("Login failed: " + e.getMessage());
			FacesMessage facesMsg = new FacesMessage(
					FacesMessage.SEVERITY_ERROR, "Error", "login.failed");
			FacesContext.getCurrentInstance().addMessage(null, facesMsg);

			return null;
		}

		SavedRequest savedRequest = (SavedRequest) getSessionParam("SPRING_SECURITY_SAVED_REQUEST");
		if (savedRequest != null) {
			try {
				String url = savedRequest.getRedirectUrl();
				log.info("Redirecting to: " + url);
				redirect(url);
			} catch (IOException e) {
				log.warn("I/O error: " + e.getMessage());
				FacesMessage facesMsg = new FacesMessage(
						FacesMessage.SEVERITY_ERROR, "Error", "io.error");
				FacesContext.getCurrentInstance().addMessage(null, facesMsg);
			}
		}

		return "success";
	}

	/**
	 * Do logout.
	 */
	public String doLogout() {
		Authentication authentication = SecurityContextHolder.getContext()
				.getAuthentication();
		if (authentication != null) {
			new SecurityContextLogoutHandler().logout(getRequest(),
					getResponse(), authentication);
		}
		SecurityContextHolder.getContext().setAuthentication(null);

		// try {
		// redirect("/faces/index.xhtml");
		// } catch (IOException e) {
		// log.warn("I/O error: " + e.getMessage());
		// FacesMessage facesMsg = new FacesMessage(
		// FacesMessage.SEVERITY_ERROR, "Error", "io.error");
		// FacesContext.getCurrentInstance().addMessage(null, facesMsg);
		// }
		return "logout";
	}

}